package buffbuildergui;

import java.awt.Dimension;

import java.io.PrintWriter;

import java.text.DecimalFormat;

import java.util.ArrayList;
import java.util.List;

import javax.swing.DefaultListModel;
import javax.swing.JOptionPane;

public class Property {
    private String name;
    private String value;
    private int type;
    private int optionID = 0;
    private Entity owner;
    final static int BOOLEAN = 0;
    final static int INTEGER = 1;
    final static int DOUBLE = 2;
    final static int BUFF = 3;
    final static int FINITE = 4;
    final static int QUOTED = 5;
    final static int ARBITRARY = 6;
    final static int COUNT = 7;
    final static int VOID = 8;
    final static int COLOR = 9;
    final static int NONZERO = 10;
    ArrayList<String> options = null;
    ArrayList<ArrayList<Property>> plugs = new ArrayList<>();
    
    public Property(String n,int t,Entity e) {
        super();
        name = n;
        type = t;
        owner = e;
        if(type == BOOLEAN)
            value = "FALSE";
        else if(type == INTEGER)
            value = "0";
        else if(type == DOUBLE)
            value = "0.000000";
        else if(type == BUFF) {
            value = "\"\"";
        }
        else if(type == QUOTED)
            value = "\"\"";
        else if(type == COUNT)
            value = "0";
        else if(type == COLOR)
            value = "ffffffff";
        else if(type == NONZERO)
            value = "1";
        else
            value = "";
    }
    public Property(String n,int t,ArrayList<String> o, Entity e) {
        super();
        name = n;
        type = t;
        owner = e;
        options = o;
        value = o.get(0);
    }
    
    public String getName() {
        return name;
    }
    public int getType() {
        return type;
    }
    public int getOptionID() {
        return optionID;
    }
    public String getValue() {
        return value;
    }
    public String stringify() {
        String pName = getName() + ' ' + getValue();
        if(type != COUNT && type != VOID)
        {
            if(getName().length() >= 15)
                pName = getName().substring(0,12) + "...";
            else
                pName = getName();
            pName = pName + ' ' + getValue();
        }
        return pName;
    }

    @SuppressWarnings("oracle.jdeveloper.java.semantic-warning")
    public boolean set(String newVal) {
        if(type == BOOLEAN) {
            if(newVal.equals("TRUE") || newVal.equals("FALSE")) {
                value = newVal;
                return true;
            }
        }
        else if(type == INTEGER) {
            try {
                Integer.parseInt(newVal);
                value = newVal;
                return true;
            }
            catch(Exception e) {
                
            }
        }
        else if(type == DOUBLE) {
            try{
                Double d = Double.parseDouble(newVal);
                DecimalFormat df = new DecimalFormat("0.000000");
                value = df.format(d);
                return true;
            }
            catch(Exception e) {
                
            }
        }
        else if(type == BUFF) {
            if(newVal.charAt(0) != '\"' && newVal.charAt(newVal.length()-1) != '\"') {
                newVal = "\"" + newVal + "\"";
            }
            
            
            String holder = newVal;
            newVal = newVal.substring(1,newVal.length()-1);
            for(int i = 0; i < jfMainFrame.buffList.size(); i++) {
                Buff selected = owner.ownerPanel.getMainFrame().buffList.get(i);
                if(selected.name.equals(newVal)) {
                    if(owner.ownerPanel.children.size() > 0) {
                        owner.ownerPanel.children.get(0).parents.remove(owner.ownerPanel);
                        owner.ownerPanel.children.remove(0);
                    }
                    value = holder;
                    owner.ownerPanel.children.add(selected.ownerPanel);
                    selected.ownerPanel.parents.add(owner.ownerPanel);
                    owner.ownerPanel.getMainFrame().bypass.repaint();
                    return true;
                }
            }
            int res = JOptionPane.showConfirmDialog(null,"The buff \"Buff" + newVal + "\" does not exist.  Would you like to create it?");
            if(res == JOptionPane.OK_OPTION) {
                if(owner.ownerPanel.children.size() > 0) {
                    owner.ownerPanel.children.get(0).parents.remove(owner.ownerPanel);
                    owner.ownerPanel.children.remove(0);
                }
                Buff b = new Buff(newVal);
                BuffPanel bp = new BuffPanel(newVal,b,null);
                owner.ownerPanel.getMainFrame().buffList.add(b);
                owner.ownerPanel.getMainFrame().bypass.add(bp);
                bp.frontify();
                owner.ownerPanel.getMainFrame().cm.registerComponent(bp);
                owner.ownerPanel.children.clear();
                owner.ownerPanel.children.add(bp);
                bp.parents.add(owner.ownerPanel);
                value = holder;
                owner.ownerPanel.getMainFrame().bypass.repaint();
                return true;
            }
        }
        else if(type == FINITE) {
            for(int i = 0; i < options.size(); i++) {
                if(options.get(i).equals(newVal)) {
                    value = newVal;
                    optionID = i;
                    return true;
                }
            }
        }
        else if(type == QUOTED) {
            if(newVal.length() >= 2 && newVal.charAt(0) == '\"' && newVal.charAt(newVal.length()-1) == '\"') {
                value = newVal;
                return true;
            }
            else {
                value = "\"" + newVal + "\"";
                return true;
            }
        }
        else if(type == ARBITRARY) {
            value = newVal;
            return true;
        }
        else if(type == COUNT) {
            if(newVal.length() != 8)
                return false;
            for(int i = 0; i < 8; i++) {
                char c = newVal.charAt(i);
                int num = (int)c;
                if((num > 47 && num < 58) || (num > 96 && num < 103)) {
                    // good!
                }
                else {
                    return false;
                }
            }
            value = newVal;
            return true;
        }
        else if(type == COLOR) {
            for(int i = 0; i < newVal.length(); i++) {
                char c = newVal.charAt(i);
                int ic = (int)c;
                boolean works = false;
                if(!((ic >= 48 && ic <=57) || (ic >= 65 && ic <= 70)))
                    return false;
            }
            value = newVal;
        }
        else if(type == NONZERO) {
            try {
                int resInt = Integer.parseInt(newVal);
                if(resInt == 0) {
                    JOptionPane.showMessageDialog(null, "This field cannot be zero");
                    return false;
                }
                value = newVal;
                return true;
            }
            catch(Exception e) {
                
            }
        }
        JOptionPane.showMessageDialog(null,"Please verify that you input a valid datatype for the property " + name);
        return false;
    }
    
    public void populate(DefaultListModel dlm) {
        String str = stringify();
        EntityPanel ownerPanel = owner.ownerPanel;
        dlm.addElement(str);
        ownerPanel.virtualList.add(this);
        if(type == FINITE) {
            if(plugs.size() > 0) {
                ArrayList<Property> selected = plugs.get(optionID);
                if(selected != null)
                {
                    if(selected.size() > 0) {
                        for(int i = 0; i < selected.size(); i++) {
                            Property target = selected.get(i);
                            target.populate(dlm);
                        }
                    }
                }
                else {
                    JOptionPane.showMessageDialog(null,"selected is null :(");
                }
            }
        }
    }
    
    public void populate(PrintWriter pw) {
        String str = name + ' ' + value;
        EntityPanel ownerPanel = owner.ownerPanel;
        pw.println(str);
        if(type == FINITE) {
            if(plugs.size() > 0) {
                ArrayList<Property> selected = plugs.get(optionID);
                if(selected != null)
                {
                    if(selected.size() > 0) {
                        for(int i = 0; i < selected.size(); i++) {
                            Property target = selected.get(i);
                            target.populate(pw);
                        }
                    }
                }
                else {
                    JOptionPane.showMessageDialog(null,"selected is null :(");
                }
            }
        }
    }
    
    public void overwrite(String str) {
        value = str;
        if(type == FINITE) {
            for(int i = 0; i < options.size(); i++) {
                if(options.get(i).equals(str)) {
                    optionID = i;
                }
            }
        }
    }
}
